using System;
using System.Collections.Generic;
using System.Text;
using Spectre.Console.Rendering;

namespace Spectre.Console.Internal
{
    internal sealed class HtmlEncoder : IAnsiConsoleEncoder
    {
        public string Encode(IEnumerable<Segment> segments)
        {
            var builder = new StringBuilder();

            builder.Append("<pre style=\"font-size:90%;font-family:consolas,'Courier New',monospace\">\n");

            foreach (var (_, first, _, segment) in segments.Enumerate())
            {
                if (segment.Text == "\n" && !first)
                {
                    builder.Append('\n');
                    continue;
                }

                var parts = segment.Text.Split(new[] { '\n' }, StringSplitOptions.None);
                foreach (var (_, _, last, line) in parts.Enumerate())
                {
                    if (string.IsNullOrEmpty(line))
                    {
                        continue;
                    }

                    builder.Append("<span");
                    if (!segment.Style.Equals(Style.Plain))
                    {
                        builder.Append(" style=\"");
                        builder.Append(BuildCss(segment.Style));
                        builder.Append('"');
                    }

                    builder.Append('>');
                    builder.Append(line);
                    builder.Append("</span>");

                    if (parts.Length > 1 && !last)
                    {
                        builder.Append('\n');
                    }
                }
            }

            builder.Append("</pre>");

            return builder.ToString().TrimEnd('\n');
        }

        private static string BuildCss(Style style)
        {
            var css = new List<string>();

            var foreground = style.Foreground;
            var background = style.Background;

            if ((style.Decoration & Decoration.Invert) != 0)
            {
                var temp = foreground;
                foreground = background;
                background = temp;
            }

            if ((style.Decoration & Decoration.Dim) != 0)
            {
                var blender = background;
                if (blender.Equals(Color.Default))
                {
                    blender = Color.White;
                }

                foreground = foreground.Blend(blender, 0.5f);
            }

            if (!foreground.Equals(Color.Default))
            {
                css.Add($"color: #{foreground.ToHex()}");
            }

            if (!background.Equals(Color.Default))
            {
                css.Add($"background-color: #{background.ToHex()}");
            }

            if ((style.Decoration & Decoration.Bold) != 0)
            {
                css.Add("font-weight: bold");
            }

            if ((style.Decoration & Decoration.Bold) != 0)
            {
                css.Add("font-style: italic");
            }

            if ((style.Decoration & Decoration.Underline) != 0)
            {
                css.Add("text-decoration: underline");
            }

            if ((style.Decoration & Decoration.Strikethrough) != 0)
            {
                css.Add("text-decoration: line-through");
            }

            return string.Join(";", css);
        }
    }
}
